//utf-8
#ifndef __MSG_H__
#define __MSG_H__

#include "rfmesh.h"

#define CONFIG_MSG_LIMIT        (2)    //最多允许多少消息同步传输 并行多了堵塞网络
#define MESSAGE_RECORD_COUNT    (64)   //消息记录池数量 循环覆盖
#define CONFIG_MSG_PACKAGE_SIZE (24)   //每一包携带有效数据长度 1~24
#define CONFIG_MSG_RETRY_COUNT  (30)   //消息重试多少次被丢弃
#define CONFIG_MSG_MULTIPLE_TV  (5)    //分包超时按照RTT * 倍数

//100 * 5 + (100 * 20) = 500 + 2000MS 数据包第一次发送超时时间
#define CONFIG_MSG_DEFAULT_TV  (100 * CONFIG_MSG_MULTIPLE_TV + 100 * CONFIG_MSG_RETRY_COUNT)

//限制发送时使用该标志来区分消息是否被激活
enum{
	MSG_LOCKED = 0,
	MSG_UNLOCK = 1,
};

//描述 message_srv_t->dir
enum{
    MSG_DIR_SEND = 0,
    MSG_DIR_RECV = 1,
};

//描述 message_data_t->flag
enum{
    MSG_FLAG_ACK =    (1<<0),
    MSG_FLAG_START =  (1<<1),
    MSG_FLAG_END =    (1<<2),
    MSG_FLAG_RST =    (1<<3),    //第一次上电时复位对方消息池的记录(根据ID) 问题： 只会复位第一个发送者的消息记录池
};

//message server 每个待接收或者待发送的消息包含一个该结构，用于控制消息收发，pbuf是数据地址 list是消息列表
struct message_srv_t{
	uint32_t dir;//发送方向 接收方向
	uint32_t id;
	uint32_t total_retry;//用来累加总超时次数
	uint32_t total;//数据总大小
	uint8_t *pbuf;//数据缓存到内存
	uint32_t offset;//当前发送偏移
	uint8_t retry;//重试次数 重试10次结束传输
	uint8_t msgsn;//每帧消息一个sn
	uint8_t pkgsn;//每个分包一个SN，主要用于计算RTT时去除超时包
	uint32_t frame_size;//每一帧分包发送字节个数
	uint8_t lock;//用于限定同时发送的消息数量
	uint32_t timeout;//接收总超时或发送重试：timeout = rtt * CONFIG_MSG_MULTIPLE_TV   
	uint32_t timebase;//timeout 的时间基准，(current_time - timebase) > timeout
	uint32_t rtt;//Round Trip Time 帧回复时间 = (发送分包->接收到回复)
	uint32_t rtt_tv;//RTT测量开始时间
	struct list_head list;
};


//message frame  消息按帧分包传输时使用该结构打包 占用8字节
struct message_data_t{
	uint32_t total:16;
	uint32_t offset:16;
	uint32_t msgsn:8;//整体消息的SN
	uint32_t pkgsn:8;//分包SN，包含重试，顺序用offset规范
	uint32_t length:8;
	uint32_t flag:8;
	uint8_t  data[24];
};

//message func  实现消息功能的全局变量 list 是 message_srv_t 列表
struct message_t{
	uint32_t sn:8;
	uint32_t tv:24;
	void (*send)(uint8_t,void *);
	uint16_t record[MESSAGE_RECORD_COUNT];
	struct list_head list;
};


void message_server(void);
void message_input(uint8_t id, void *pdata);
void message_init(void (*send)(uint8_t,void *));
int message_write(uint8_t id, void *pdata, int length);

#endif
